#include "HiloModelo.h"
#include <string>
#include <sstream>
#include <openssl/hmac.h>
#include "MensajeServidor.h"
#include "Moderador.h"

using std::string;

HiloModelo::HiloModelo(Moderador* queue, int nivelAJugar){
	this->queue=queue;
	nivel = nivelAJugar;
}

void HiloModelo::setIdAdmin(int id){
	idAdmin=id;
}


void* HiloModelo::run() {
	string mensaje;
	Partida p(nivel);
	MensajeServidor msj;
	int idClienteMov;
	int puntos;
	p.validarTablero();
	mensaje = msj.setTableroInicial(p.getCeldas(), p.getFilas(),
			p.getColumnas(), queue->getVecJsonPuntajes(idAdmin));
	queue->enviarMensaje(mensaje, idAdmin);
	while(1){
		while(queue->hayDatos(idAdmin)==false){}
		mensaje=queue->getMensaje(idAdmin);
		Json::Value vJsonFull = msj.convertJson(mensaje);
		Json::Value msjJsonFinal(Json::objectValue);
		idClienteMov = queue->getIdClienteMensaje(idAdmin);
		// La key para el hasheo
		std::string key = (queue->getKey(idAdmin, idClienteMov));
		//longitud que necesita el sha1
		if((vJsonFull["flag"].asString().compare("m") == 0)){
			Json::Value vJson = vJsonFull["original"];
			unsigned int len = 20;
			unsigned char* origHasheado;
			unsigned char* hasheado;
			origHasheado = (unsigned char*)malloc(sizeof(char) * len);
			HMAC_CTX ctx;
			HMAC_CTX_init(&ctx);
			hasheado = (unsigned char*)malloc(sizeof(char) * len);
			string h = vJsonFull["hasheado"].asString();
			hasheado = (unsigned char*)h.c_str();

			// Se usa sha1 como motor de hasheo
			HMAC_Init_ex(&ctx, key.c_str(), strlen(key.c_str()), EVP_sha1(), NULL);
			HMAC_Update(&ctx, (unsigned char*)vJsonFull["original"].toStyledString().c_str(),
					strlen(vJsonFull["original"].toStyledString().c_str()));
			HMAC_Final(&ctx, origHasheado, &len);
			HMAC_CTX_cleanup(&ctx);
			int c1;
			int c2;
			c1 = vJson["c1"].asInt();
			c2 = vJson["c2"].asInt();
			Json::Value mValido;
			if (*hasheado == *origHasheado){

				//free(hasheado);
				Json::Value msjBloqueo;
				msjBloqueo["flag"] = "b";
				queue->enviarMensajeParticular(msjBloqueo.toStyledString(),
													idAdmin, idClienteMov, 1);
				msjBloqueo["intercambio"] = true;
				//este es el cliente que origino el movimiento
				msjBloqueo["celda1"] = c1;
				msjBloqueo["celda2"] = c2;
				queue->enviarMensajeParticular(msjBloqueo.toStyledString(),
													idAdmin, idClienteMov, 0);
				Json::Value vecJugadas(Json::arrayValue);
				p.setMultiplicador(1);
				Posicion p1(c1%p.getFilas(),c1/p.getFilas());
				Posicion p2(c2%p.getFilas(),c2/p.getFilas());
				bool movValido = p.intercambiarGolosinas(p1,p2);
				if(!movValido){
					mValido["valido"] = false;
					mValido["celda1"] = c1;
					mValido["celda2"] = c2;
				}else {
					mValido["valido"] = true;
					vecJugadas.append(p.vecToJson());
					puntos += p.getPuntosJugada();
					p.limpiarVectores();
					p.vaciarPuntosJugada();
					while(p.verificarMatchs()){
						p.setMultiplicador(p.getMultiplicador() + 1);
						vecJugadas.append(p.vecToJson());
						puntos += p.getPuntosJugada();
						p.limpiarVectores();
						p.vaciarPuntosJugada();
					}
					mValido["jugadas"] = vecJugadas;
					queue->sumarPuntos(puntos, idAdmin);
					mValido["puntajes"] = queue->getVecJsonPuntajes(idAdmin);

				}
				mValido["flag"] = "j";
				mensaje = mValido.toStyledString();
				queue->enviarMensaje(mensaje, idAdmin);
				if (queue->getPuntosCliente(idAdmin) >= p.getMaxPuntos()){
					Json::Value fin;
					string user;
					fin["flag"] = "ganaste";
					queue->enviarMensajeParticular(fin.toStyledString(),
														idAdmin, idClienteMov, 1);
					user = queue->getUserClienteMensaje(idAdmin);
					Login::sumarNivelUsuario(user, nivel);

					fin["flag"] = "perdiste";
					queue->enviarMensajeParticular(fin.toStyledString(),
														idAdmin, idClienteMov, 0);
				}
				free(origHasheado);
			} else{
				mValido["valido"] = false;
				mValido["celda1"] = c1;
				mValido["celda2"] = c2;
			}
		}else if (vJsonFull["flag"].asString().compare("q") == 0){
			idClienteMov = queue->getIdClienteMensaje(idAdmin);
			Json::Value msjJson;
			msjJson["flag"] = "q";
			queue->enviarMensajeParticular(msjJson.toStyledString(),
												idAdmin, idClienteMov, 1);
		}
		puntos = 0;
	}
	return NULL;
}

